package cn.im.qywx.controller;

import cn.im.qywx.model.ImWxUserInfo;
import cn.im.qywx.queue.UserQueue;
import cn.im.qywx.service.ImWxUserInfoService;
import cn.im.qywx.util.DateUtils;
import cn.im.qywx.util.aes.AesException;
import cn.im.qywx.util.aes.SampleUtils;
import cn.im.qywx.util.aes.WXBizMsgCrypt;
import cn.im.qywx.view.WeiXinXml;
import cn.im.qywx.wx.Message;
import cn.im.qywx.wx.type.MessageType;
import cn.im.qywx.wx.util.AnalyzeWeiXinMsgXml;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 微信入口
 */
@RestController
@Scope("prototype")
@Slf4j
public class WeiXinController {

    private static final String unSubscribe = "unSubscribe";
    private static final String noReturn = "noReturn";
    private static final String sToken = "BEwMypovubuvBvIMBIWywXQWb9Zn";
    private static final String sEncodingAESKey = "WeeoHuUubLafrB7OlifcqxF67i9bxCJKJw1NdxD1aTE";

    /**
     * 默认回复
     */
    private static final String DEFAULT_RSP = "更多功能等待开发中...";

    @Autowired
    ImWxUserInfoService userService;

    /**
     * 微信接入参
     */
    @RequestMapping(value = "/w")
    public String weiXinEntrance(HttpServletRequest request, HttpServletResponse response, @RequestBody String postData) {

        String responseStr = null;
        String msgSignature = null;
        String timestamp = null;
        String nonce = null;
        String echostr = null;

        msgSignature = request.getParameter("msg_signature");
        timestamp = request.getParameter("timestamp");
        nonce = request.getParameter("nonce");
        echostr = request.getParameter("echostr");

        log.info("getRequestURI:" + request.getRequestURI());

        // 获取请求方式的类型
        String method = request.getMethod().toUpperCase();

        /* 处理请求 */
        if ("POST".equals(method)) { // 消息请求

            log.info("postData=" + postData);
            postData = SampleUtils.getInstance().DecryptMsg(msgSignature, timestamp, nonce, postData);
            responseStr = processMsg(postData);

            if (StringUtils.isEmpty(responseStr)) {// 返回结果为空的时候一律返回欢迎主导航
                responseStr = DEFAULT_RSP;
            } else if (unSubscribe.equals(responseStr) || noReturn.equals(responseStr)) {  //取消关注or处理异常
                return "ok";
            }
            responseStr = SampleUtils.getInstance().EncryptMsg(responseStr, timestamp, nonce);

        } else { // 验证请求
            try {
                WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, "wx83b404b710b8ed05");
                responseStr = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
                log.info("verifyurl echostr: " + responseStr);
            } catch (AesException e) {
                log.info(" wx WXBizMsgCrypt method return exception.");
                e.printStackTrace();
            }
        }
        log.info("responseStr:" + responseStr);

        return responseStr;
    }



    /**
     * 处理用户消息请求 1、接收request输入流 2、转换成String - XML 3、解析XML - XMLObject
     */
    private String processMsg(String msgXml) {

        String pubStr;// 公共参数
        String returnStr = null;
        WeiXinXml wxXml = null;// 接收到的消息
        ImWxUserInfo userInfo;// 用户信息
        int userInWhere;// 用户在那个队列
        Message message;// 模式-消息
        long pTime;
        pTime = System.currentTimeMillis();

        // 解析XML - XML to Object----------------------
        if (!StringUtils.isEmpty(msgXml)) {
            log.info(DateUtils.date2String(new Date(), "yyyyMMdd HH:mm:ss") + "msg from user：\n" + msgXml);

            wxXml = new WeiXinXml();
            wxXml.setUserSendXml(msgXml);
            AnalyzeWeiXinMsgXml.analyze(msgXml, wxXml);

            msgXml = null;
        }

        // 处理接收到的数据--------------------------
        if (null != wxXml) {

            // 确定用户发送内容的类型-----------------------
            pubStr = Message.getMsgType(wxXml.getMsgType());
            if (!pubStr.equals(MessageType.NOTFOUND.name())) {

                if (pubStr.equals(MessageType.EVENT.name())) {// 获取事件类型
                    pubStr = Message.getMsgType(wxXml.getEvent());
                }

                wxXml.setMessageType(pubStr);// 设置用户发送的内容类型对应的程序内部类型

                // [获取 or 创建] 用户-------------------------
                userInWhere = userService.getUserInWhere(wxXml.getFromUserName(), wxXml.getToUserName());// 查询用户所在
                userInfo = (ImWxUserInfo) UserQueue.userInfoMapManager(0, wxXml.getFromUserName(), null);// 获取队列中的用户
                userInfo.getQueueInfo().setWxXml(wxXml);// 设置xml对象
                userInfo.getQueueInfo().setUserInWhere(userInWhere);// 设置用户从那个队列来


                // 选择用户队列进入处理模式-------------------------------
                log.info("userMode:" + userInfo.getQueueInfo().getUserMode());
                log.info("MessageType:" + Enum.valueOf(MessageType.class, wxXml.getMessageType()));
                message = Message.messageSelector(userInfo.getQueueInfo().getUserMode(), Enum.valueOf(MessageType.class, wxXml.getMessageType()));// 选择用户处理模式
                message.execute(userInfo);// 进入相应的处理模式

                //log.info("请求信息-----类型："+userInfo.getQueueInfo().getWxXml().getMessageType());

                //用户不是取消关注，但状态又是取消关注
				/*if(!MessageType.UNSUBSCRIBE.equals(Enum.valueOf(MessageType.class, wxXml.getMessageType())) && userInfo.getQueueInfo().isUnSubscribe()){
					userInfo.getQueueInfo().setUnSubscribe(false);
				}*/

                if (userInfo.getQueueInfo().isUnSubscribe()) {// 用户取消关注
                    userInfo = null;
                    returnStr = unSubscribe;
                    return returnStr;
                }

                if (null == userInfo.getQueueInfo().getWxXml()) {// 不需要返回
                    returnStr = noReturn;
                } else {
                    // 设置发送给用户的返回值------------------------------------
                    returnStr = userInfo.getQueueInfo().getWxXml().getServerSendXml();
                    log.info(DateUtils.date2String(new Date(), "yyyyMMdd HH:mm:ss") + "响应：\n" + returnStr);
                }

                // 将用户存入队列中------------------------------------
                userInfo.setEndvisittime(new Date());// 设置最后访问时间
                UserQueue.userInfoMapManager(1, userInfo.getWeixinno(), userInfo);// 将数据保存到队列中

                // 保存本次处理日志------------------------------
                //LogsQueue.setLog(wxXml, sessid, "2", (System.currentTimeMillis() - pTime), null == userInfo.getQueueInfo().getCTpye() ? "" : userInfo.getQueueInfo().getCTpye().name());
            }
        }

        msgXml = null;
        wxXml = null;
        message = null;

        return returnStr;
    }

}
